App.require(["matrix3"], function (matrix3) {
    var Matrix3 = matrix3.Matrix3;
    App.defineWidget("radar", {
        render: function (ctx) {
            ctx.save();
            var style = this.style;
            if (style.option.length == 0) return ctx.restore();
            ctx.globalAlpha = style.opacity;

            ctx.translate(style.x, style.y);
            var start = style.startoffset, steps = style.steps, options = style.option;
            if (style.helpfill) {
                ctx.save();
                var fills = style.helpfill;
                for (var i = 0; i < steps; i++) {
                    var stepLen = style.r * i / steps, nextStepLen = style.r * (i + 1) / steps,
                        cps = this._getPoints(stepLen, options.length, start),
                        nps = this._getPoints(nextStepLen, options.length, start);

                    ctx.beginPath();
                    ctx.moveTo(cps[0].x, cps[0].y);
                    for (var j = 1; j < cps.length; j++) {
                        ctx.lineTo(cps[j].x, cps[j].y);
                    }
                    ctx.closePath();
                    ctx.moveTo(nps[0].x, nps[0].y);
                    for (var j = nps.length - 1; j >= 1; j--) {
                        ctx.lineTo(nps[j].x, nps[j].y);
                    }
                    ctx.closePath();
                    var fillStr = this._getStepColor(fills, i);
                    ctx.fillStyle = fillStr;
                    ctx.fill();
                }
                ctx.restore();
            }

            var strokes = style.helpstroke;
            for (var i = 1; i <= steps; i++) {
                var stepLen = style.r * i / steps,
                    nps = this._getPoints(stepLen, options.length, start);

                ctx.beginPath();
                ctx.moveTo(nps[0].x, nps[0].y);
                for (var j = 1; j < nps.length; j++) {
                    ctx.lineTo(nps[j].x, nps[j].y);
                }
                ctx.closePath();
                var strokeStr = this._getStepColor(strokes, i);
                ctx.strokeStyle = strokeStr;
                ctx.stroke();
            }

            var shadowObj = App.Widget.strToShadow(style.shadow);
            if (shadowObj) {
                ctx.shadowOffsetX = shadowObj.x;
                ctx.shadowOffsetY = shadowObj.y;
                ctx.shadowBlur = shadowObj.blur;
                ctx.shadowColor = shadowObj.color;
            }
            

            ctx.beginPath();
            for (var i = 0; i < options.length; i++) {
                var obj = options[i], p = this._getRadiusPoints(obj, i, options.length, start, style.percent);
                if (i == 0) ctx.moveTo(p.x, p.y);
                else ctx.lineTo(p.x, p.y);
            }
            ctx.closePath();
            if (style.fill) {
                ctx.fillStyle = style.fill;
                ctx.fill();
            }
            if (style.stroke) {
                ctx.strokeStyle = style.stroke;
                ctx.stroke();
            }
            ctx.restore();
        },
        isPointIn: function (ctx, x, y) {
            var style = this.style, start = style.startoffset, options = style.option;
            ctx.save();
            ctx.translate(style.x, style.y);
            var nps = this._getPoints(style.r, options.length, start);

            ctx.beginPath();
            ctx.moveTo(nps[0].x, nps[0].y);
            for (var j = 1; j < nps.length; j++) {
                ctx.lineTo(nps[j].x, nps[j].y);
            }
            ctx.closePath();
            var isIn = ctx.isPointInPath(x, y);
            ctx.restore();
            return isIn;
        },
        _getRadiusPoints: function (obj, i, len, start, percent, ratio) {
            ratio = ratio || 1;
            var value = parseFloat(obj.value) * ratio * percent;
            var theta = 2 * Math.PI * i / len + start;
            return {
                x: Math.cos(theta) * value, y: Math.sin(theta) * value
            }
        },
        _getPoints: function (r, len, start) {
            start = start || 0;
            var result = [];
            for (var i = 0; i < len; i++) {
                var theta = 2 * Math.PI * i / len + start;
                result.push({ x: Math.cos(theta) * r, y: Math.sin(theta) * r});
            }
            return result;
        },
        _getStepColor: function (opts, i) {
            return opts[i % opts.length];
        },
        style: {
            steps: 5,
            r: 100,
            x: 0,
            y: 0,
            direction: App.PieDirectionOption.CCW,
            startoffset: 0,
            max: "",
            shadow: "0 0 0 black",
            stroke: "green",
            fill: "rgba(0,0,0,0.5)",
            helpstroke: ["black", "red"],
            helpfill: ["white", "green"],
            mark: "",
            markOffset: "",
            marker: "",
            markerOffset: "",
            opacity: 1,
            linewidth: 1,
            percent: 1,
            linedash: "",
            linedashoffset: 0,
            option: [ { value: 40 }, { value: 80 }, { value: 60 } ]
        },
        get steps() {
            return this.style.steps;
        },
        set steps(val) {
            this.style.steps = val;
            this.getScene().nextRender();
        },
        get r() {
            return this.style.r;
        },
        set r(val) {
            this.style.r = val;
            this.getScene().nextRender();
        },
        get x() {
            return this.style.x;
        },
        set x(val) {
            this.style.x = val;
            this.getScene().nextRender();
        },
        get y() {
            return this.style.y;
        },
        set y(val) {
            this.style.y = val;
            this.getScene().nextRender();
        },
        get direction() {
            return this.style.direction;
        },
        set direction(val) {
            this.style.direction = val;
            this.getScene().nextRender();
        },
        get startoffset() {
            return this.style.startoffset;
        },
        set startoffset(val) {
            this.style.startoffset = val;
            this.getScene().nextRender();
        },
        get max() {
            return this.style.max;
        },
        set max(val) {
            this.style.max = val;
            this.getScene().nextRender();
        },
        get mark() {
            return this.style.mark;
        },
        set mark(val) {
            this.style.mark = val;
            this.getScene().nextRender();
        },
        get markOffset() {
            return this.style.markOffset;
        },
        set markOffset(val) {
            this.style.markOffset = val;
            this.getScene().nextRender();
        },
        get marker() {
            return this.style.marker;
        },
        set marker(val) {
            this.style.marker = val;
            this.getScene().nextRender();
        },
        get markerOffset() {
            return this.style.markerOffset;
        },
        set markerOffset(val) {
            this.style.markerOffset = val;
            this.getScene().nextRender();
        },
        get shadow() {
            return this.style.shadow;
        },
        set shadow(val) {
            this.style.shadow = val;
            this.getScene().nextRender();
        },
        get stroke() {
            return this.style.stroke;
        },
        set stroke(val) {
            this.style.stroke = val;
            this.getScene().nextRender();
        },
        get fill() {
            return this.style.fill;
        },
        set fill(val) {
            this.style.fill = val;
            this.getScene().nextRender();
        },
        get helpfill() {
            return this.style.helpfill;
        },
        set helpfill(val) {
            this.style.helpfill = val;
            this.getScene().nextRender();
        },
        get helpstroke() {
            return this.style.helpstroke;
        },
        set helpstroke(val) {
            this.style.helpfill = val;
            this.getScene().nextRender();
        },
        get opacity() {
            return this.style.opacity;
        },
        set opacity(val) {
            this.style.opacity = val;
            this.getScene().nextRender();
        },
        get percent() {
            return this.style.percent;
        },
        set percent(val) {
            this.style.percent = val;
            this.getScene().nextRender();
        },
        get linewidth() {
            return this.style.linewidth;
        },
        set linewidth(val) {
            this.style.linewidth = val;
            this.getScene().nextRender();
        },
        get linedash() {
            return this.style.linedash;
        },
        set linedash(val) {
            this.style.linedash = val;
            this.getScene().nextRender();
        },
        get linedashoffset() {
            return this.style.linedashoffset;
        },
        set linedashoffset(val) {
            this.style.linedashoffset = val;
            this.getScene().nextRender();
        }
    })
})